package edu.hawaii.myisern.action;

import java.util.Iterator;
import java.util.List;
import javax.xml.bind.JAXBException;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import org.xml.sax.SAXException;
import edu.hawaii.myisern.model.MyIsernModel;
import edu.hawaii.myisern.organizations.jaxb.AffiliatedResearchers;
import edu.hawaii.myisern.organizations.jaxb.Organization;
import edu.hawaii.myisern.organizations.jaxb.ResearchKeywords;
import edu.hawaii.myisern.xmldatabase.XmlLoader;

/**
 * ActionBean for Organization, both listing and editing.
 * 
 * @author Shaoxuan Zhang
 * @author Laura Matsuo
 *
 */
public class OrganizationActionBean extends MyIsernActionBean {
  /** MyIsern instance manipulated by all webapp users. */
  private MyIsernModel myIsern = MyIsernModel.getInstance();
  /** Our single organization instance manipulated by all webapp users. */
  private Organization organization = new Organization();
  private String message = "";
  private String affiliatedResearchers = null;
  private String researchKeywords = null;

  /**
   * Constructor
   * 
   * @throws JAXBException when JAXB fails.
   * @throws SAXException when SAX fails.
   */
  public OrganizationActionBean() throws JAXBException, SAXException {
    // empty constructor
  }

  /**
   * Gets the message to display to the user, such as when a organization has been added.
   * 
   * @return The message to display to the user.
   */
  public String getMessage() {
    return this.message;
  }

  /**
   * Set the message to display to the user, such as when a organization has been added.
   * 
   * @param message The message to display to the user.
   */
  public void setMessage(String message) {
    this.message = message;
  }

  /**
   * Return the name of this organization.
   * 
   * @return - a String
   */
  public String getName() {
    return this.organization.getName();
  }

  /**
   * Sets the name of the organization.
   * 
   * @param name The name of the organization.
   */
  public void setName(String name) {
    this.organization.setName(name);
  }

  /**
   * Return the type of this organization.
   * 
   * @return - a String
   */
  public String getType() {
    return this.organization.getType();
  }

  /**
   * Set the type.
   * 
   * @param type - String of given value.
   */
  public void setType(String type) {
    this.organization.setType(type);
  }

  /**
   * Return the Contact of this organization.
   * 
   * @return - a String
   */
  public String getContact() {
    return this.organization.getContact();
  }

  /**
   * Set the Contact.
   * 
   * @param contact - String of given value.
   */
  public void setContact(String contact) {
    this.organization.setContact(contact);
  }

  /**
   * Return the Affiliated Researchers of this organization.
   * 
   * @return - a List of String
   */
  public Iterator<String> getAffiliatedResearchersIterator() {
    return this.organization.getAffiliatedResearchers().getAffiliatedResearcher().iterator();
  }

  /**
   * Return the String represents Affiliated Researchers of this organization.
   * 
   * @return - A String.
   */
  public String getAffiliatedResearchers() {
    if (this.affiliatedResearchers == null) {
      this.affiliatedResearchers = XmlLoader.joinListToString(this.organization
          .getAffiliatedResearchers().getAffiliatedResearcher(), "\n");
    }
    return this.affiliatedResearchers;
  }

  /**
   * Sets the organization's Affiliated Researchers of this organization.
   * 
   * @param affiliatedResearchers The organization's affiliated researchers.
   */
  public void setAffiliatedResearchers(String affiliatedResearchers) {
    this.affiliatedResearchers = affiliatedResearchers;
    organization.setAffiliatedResearchers(new AffiliatedResearchers());
    organization.getAffiliatedResearchers().getAffiliatedResearcher().addAll(
        XmlLoader.splitStringToList(this.affiliatedResearchers, "\n"));
  }

  /**
   * Return the Country of this organization.
   * 
   * @return - a String
   */
  public String getCountry() {
    return this.organization.getCountry();
  }

  /**
   * Set the Country.
   * 
   * @param country - String of given value.
   */
  public void setCountry(String country) {
    this.organization.setCountry(country);
  }

  /**
   * Return the Research Keywords of this organization.
   * 
   * @return - a String
   */
  public Iterator<String> getResearchKeywordsIterator() {
    return this.organization.getResearchKeywords().getResearchKeyword().iterator();
  }

  /**
   * Return a String represents Research Keywords of this organization.
   * 
   * @return - a String
   */
  public String getResearchKeywords() {
    if (this.researchKeywords == null) {
      this.researchKeywords = XmlLoader.joinListToString(this.organization.getResearchKeywords()
          .getResearchKeyword(), "\n");
    }
    return this.researchKeywords;
  }

  /**
   * Set the Research Keywords of this organization.
   * 
   * @param researchKeywords - A String that represent the research keywords.
   */
  public void setResearchKeywords(String researchKeywords) {
    this.researchKeywords = researchKeywords;
    organization.setResearchDescription(this.getResearchDescription());
    organization.setResearchKeywords(new ResearchKeywords());
    organization.getResearchKeywords().getResearchKeyword().addAll(
        XmlLoader.splitStringToList(this.researchKeywords, "\n"));
  }

  /**
   * Return the Research Description of this organization.
   * 
   * @return - a String
   */
  public String getResearchDescription() {
    return this.organization.getResearchDescription();
  }

  /**
   * Set ResearcherDescription.
   * 
   * @param value - String of given value.
   */
  public void setResearchDescription(String value) {
    this.organization.setResearchDescription(value);
  }

  /**
   * Return the HomePage of this organization.
   * 
   * @return - a String
   */
  public String getHomePage() {
    return this.organization.getHomePage();
  }

  /**
   * Set HomePage.
   * 
   * @param value - String of given value.
   */
  public void setHomePage(String value) {
    this.organization.setHomePage(value);
  }

  /**
   * Provides an iterator over the organizations to the page.
   * 
   * @return The organizations iterator.
   */
  public Iterator<Organization> getOrganizationsIterator() {
    return this.myIsern.getOrganizationList().iterator();
  }

  /**
   * Returns all organizations as a list.
   * 
   * @return  All organizations.
   */
  public List<Organization> getOrganizationList() {
    return this.myIsern.getOrganizationList();
  }

  /**
   * Return a list of invalid referencer of researcher within this organization.
   * @return a List of String.
   */
  public List<String> getInvalidReferenceInOrganization() {
    return this.myIsern.getInvalidReference(this.organization);
  }

  /**
   * Updates the organization's information if the organization already exists in the list,
   * otherwise adds the organization to the list.
   * 
   * @return A Resolution indicating to display the organizationDisplayMessage.jsp page.
   */
  public Resolution save() {
    if (this.organization.getName() == null || this.organization.getName().length() == 0) {
      this.message = "Nothing is added.";
    }
    //Check if there is any invalid information
    else if (this.myIsern.semanticCheck(this.organization)) {
      this.myIsern.add(this.organization);
      this.message = "There are invalid information within your input.";
      return new ForwardResolution("/organizationError.jsp");
    }
    //See if it is a new organization.
    else if (this.myIsern.add(this.organization)) {
      this.message = " Thank you for entering Organization " + this.organization.getName();
    }
    else {
      this.message = "Organization " + this.organization.getName() + " has been updated.";
    }
    return new ForwardResolution("/organizationsList.jsp");
  }

  /**
   * Finds the organization to edit if the organization already exists.
   * 
   * @return A Resolution indicating to display the organizationEdit.jsp page.
   */
  public Resolution edit() {
    this.organization = this.myIsern.getOrganization(getName());
    if (this.organization == null) {
      this.organization = new Organization();
      this.organization.setResearchKeywords(new ResearchKeywords());
      this.organization.setAffiliatedResearchers(new AffiliatedResearchers());
    }
    return new ForwardResolution("/organizationEdit.jsp");
  }

  /**
   * Finds the organization to display.
   * 
   * @return A Resolution indicating to display the organizationView.jsp page.
   */
  public Resolution view() {
    if (this.myIsern.hasOrganization(this.getName())) {
      this.organization = this.myIsern.getOrganization(this.getName());
      return new ForwardResolution("/organizationView.jsp");
    }
    else {
      return new ForwardResolution("/organizationNotExist.jsp");
    }
  }

  /**
   * Deletes the organization specified by name.
   * 
   * @return A Resolution indicating to display the organizationDisplayMessage.jsp page.
   */
  public Resolution delete() {
    if (this.myIsern.remove(this.getName())) {
      this.message = "Organization: " + this.getName() + "was successfully deleted";
    }
    else {
      this.message = "Organization: " + this.getName() + "not found. Maybe delete by other users";
    }
    return new ForwardResolution("/organizationsList.jsp");
  }

  /**
   * Forwards the user to the organizationsList.jsp page to view all researchers.
   * 
   * @return A Resolution indicating to redisplay the organizationsList.jsp page.
   */
  @DefaultHandler
  public Resolution listOrganizations() {
    // organizations.listOrganizations();
    return new ForwardResolution("/organizationsList.jsp");
  }
}
